<template>
  <div class="container">
    <div class="app-container">
      <!-- 添加按钮 -->
      <div>
        <el-button type="primary" @click="isShow = true">添加角色</el-button>
      </div>
      <!-- 表格主体 -->
      <!--
        三个属性 + 插槽
          el-table 的data属性
          el-table-column  的label  prop属性
       -->
      <el-table :data="list" class="aaa">
        <!-- align="center" 让列的标题和内容居中 -->
        <!-- type="index" 的作用，把这一列变成序号 -->
        <el-table-column align="center" label="序号" type="index" />
        <el-table-column align="center" label="角色" prop="name">
          <template #default="{ row }">
            <span v-if="!row.isEdit">{{ row.name }}</span>
            <el-input v-else v-model="row.editRow.name" size="mini" />
          </template>
        </el-table-column>
        <el-table-column align="center" label="启用" prop="state">
          <template v-slot:default="{ row }">
            <!-- {{ row }} -->
            <span v-if="!row.isEdit">{{ row.state === 1 ? "已启用" : "未启用" }}</span>
            <el-switch v-else v-model="row.editRow.state" :inactive-value="0" :active-value="1" />
          </template>
        </el-table-column>
        <el-table-column align="center" label="描述" prop="description">
          <template #default="{row}">
            <span v-if="!row.isEdit">{{ row.description }}</span>
            <el-input v-else v-model="row.editRow.description" type="textarea" size="mini" />
          </template>
        </el-table-column>
        <el-table-column align="center" label="操作">
          <template v-slot:default="{ row }">
            <div v-if="!row.isEdit">
              <el-button size="mini" type="text" @click="btnPerm(row)">分配权限</el-button>
              <el-button size="mini" type="text" @click="editRow(row)">编辑</el-button>
              <el-button size="mini" type="text">删除</el-button>
            </div>
            <div v-else>
              <el-button type="primary" size="mini" @click="updateRole(row)">确定</el-button>
              <el-button size="mini" @click="row.isEdit = false">取消</el-button>
            </div>
          </template>
        </el-table-column>
      </el-table>
      <!-- 分页组件 -->
      <el-row type="flex" justify="end">
        <!--
          4个属性 + 一个事件
          current-page 当前页码
          page-size    每页记录数
          total        总的记录数
         -->
        <el-pagination
          :current-page="queryParams.page"
          :page-size="queryParams.pagesize"
          :total="total"
          layout="prev, pager, next"
          @current-change="currentChange"
        />
      </el-row>
    </div>
    <!-- 新增角色的弹出层 -->
    <el-dialog
      width="500px"
      title="新增角色"
      :visible.sync="isShow"
      @close="btnCancel"
    >
      <!-- 表单内容 -->
      <el-form ref="form" label-width="120px" :model="formData" :rules="rules">
        <el-form-item label="角色名称" prop="name">
          <el-input v-model="formData.name" style="width: 300px" size="mini" />
        </el-form-item>
        <el-form-item label="启用">
          <!--
            和el-switch开关组件绑定的变量，默认得到值是true和false
            但是我们这里调接口要求使用数据是 1 和 0
            所以我们通过active-value指定打开时的值
            通过inactive-value指定关闭时的值
           -->
          <el-switch
            v-model="formData.state"
            :active-value="1"
            :inactive-value="0"
          />
        </el-form-item>
        <el-form-item label="角色描述" prop="description">
          <el-input v-model="formData.description" type="textarea" style="width: 300px" size="mini" />
        </el-form-item>
        <el-form-item>
          <el-row type="flex" justify="center">
            <el-col :span="12">
              <el-button
                type="primary"
                size="mini"
                @click="addRole"
              >确定</el-button>
              <el-button size="mini" @click="btnCancel">取消</el-button>
            </el-col>
          </el-row>
        </el-form-item>
      </el-form>
    </el-dialog>
    <!-- 为角色分配权限的弹出层 -->
    <!-- 放置分配权限的弹出层 -->
    <el-dialog
      title="分配权限"
      :visible.sync="isShowPermDialog"
    >
      <!--
        show-checkbox  在每个树节点前展示复选框
        default-checked-keys  设置默认选中的节点
        node-key="id" 指定唯一标识
        check-strictly 设置为true, 父子不关联
      -->
      <el-tree
        v-if="isShowPermDialog"
        ref="permTree"
        :data="perms"
        :props="{label: 'name'}"
        default-expand-all
        show-checkbox
        node-key="id"
        check-strictly
        :default-checked-keys="permIds"
      />
      <el-row type="flex" justify="center">
        <el-button type="primary" size="mini" @click="ssignPrem">确定</el-button>
        <el-button size="mini" @click="isShowPermDialog = false">取消</el-button>
      </el-row>
    </el-dialog>
  </div>
</template>
<script>
import {
  getRoleList,
  addRole,
  updateRole,
  getRoleDetail,
  assignPrem
} from '@/api/role'
import { getPermissionList } from '@/api/permission'
import { transListToTreeData } from '@/utils'

// 两个变量四个属性
export default {
  name: 'Role',
  data() {
    return {
      // 请求的分页参数
      queryParams: {
        page: 1,
        pagesize: 5
      },
      // 响应的分页参数
      total: 0,
      list: [
        // {
        //   id: 1,
        //   name: '系统管理员',
        //   state: 0,
        //   description: 'aaa'
        // }
      ],
      isShow: false, // 控制弹出层的显示和隐藏
      formData: {
        name: '',
        description: '',
        state: 0 // 0 不启用  1 启用 （默认给不启用）
      },
      rules: {
        name: [
          { required: true, message: '角色名称不能为空', trigger: 'blur' }
        ],
        description: [
          { required: true, message: '角色描述不能为空', trigger: 'blur' }
        ]
        // state 是一个开关，所以没有必要做非空校验
      },
      isShowPermDialog: false, // 是否展示分配权限的弹出层
      perms: [], // 放权限树型数组
      permIds: [] // 放当前角色拥有的权限的id组成的数组
    }
  },
  created() {
    this.getList()
  },
  methods: {
    // 点分配权限
    async btnPerm(row) {
      // 调获取权限的接口，拿到扁平的权限数组
      const res = await getPermissionList()
      // 转成树型的，丢到变量上
      this.perms = transListToTreeData(res, 0)
      // 调接口获取当前角色拥有的权限id组成数组
      const { permIds } = await getRoleDetail(row.id)
      // 修改permIds，设置默认勾选的复选框
      this.permIds = permIds
      // 把弹出层展示出来
      this.isShowPermDialog = true
      // 点分配权限的时候，把当前点击的角色的id记录下来
      this.currentId = row.id
    },
    // 点分配权限弹层层的确定
    async ssignPrem() {
      // 调为角色分配权限的接口
      // console.log(this.$refs.permTree.getCheckedKeys()) // [3, 4, 5]
      await assignPrem(this.currentId, this.$refs.permTree.getCheckedKeys())
      // 关闭弹层
      this.$message.success('为角色分配权限成功')
      this.isShowPermDialog = false
    },
    async getList() {
      // 调接口拿数据
      // const { rows, total }
      const { rows, total } = await getRoleList(this.queryParams)
      // 1. 给每个角色对象添加一个isEdit的属性，标识是否编辑中
      rows.forEach(item => {
        item.isEdit = false
        // 添加一个属性存储备份的数据对象
        item.editRow = {
          state: item.state,
          description: item.description,
          name: item.name
        }
      })
      // 并把数据放到变量上
      this.list = rows
      this.total = total
    },
    currentChange(newPage) {
      // console.log(newPage)
      //  修改页码
      this.queryParams.page = newPage
      //  重新调接口，拿指定页码的数据
      this.getList()
    },
    // 点取消
    btnCancel() {
      // 重置表单
      this.$refs.form.resetFields()
      // 关闭弹层
      this.isShow = false
    },
    // 点确定
    async addRole() {
      await this.$refs.form.validate()
      await addRole(this.formData)
      this.$message.success('新增角色成功')
      this.getList()
      this.btnCancel()
    },
    // 点编辑
    editRow(row) {
      // 利用原对象，重置备份的属性
      row.editRow.name = row.name
      row.editRow.state = row.state
      row.editRow.description = row.description
      // 把编辑状态设置为true
      row.isEdit = true
    },
    // 点确定
    async updateRole(row) {
      // 1. 检查必填项
      if (!row.editRow.name || !row.editRow.description) {
        return this.$message.error('角色名称或角色描述不能为空')
      }
      // 2. 调更新的接口
      await updateRole(row.id, {
        id: row.id,
        ...row.editRow
      })
      // 3. 提示修改成功
      this.$message.success('更新角色成功')
      // 4. 更新数据
      // this.getList()
      // 直接用备份的对象的属性 覆盖原对象
      // 浅拷贝  Object.assign(对象1, 对象2)
      // 就会把对象2的属性，拷贝到对象1身上
      Object.assign(row, row.editRow)
      // // 代码其实没有错误，是属于eslint的误判
      row.isEdit = false
    }
  }
}
</script>
<style lang="scss" scoped>
.app-container {
  padding: 30px;
}
</style>

